#include "evdeploy/deploy.h"
#include <fstream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <sstream>
#include <thread>

using namespace ev;

/**
 * 本测试是采用EVDeploy框架实现的内置 车牌检测算法的一个demo示例,
 * 可以通过该示例学习内置基础算法的使用方法,其过程跟EVDeploy的基本用法
 * 基本一致,只是进一步将模型的前后处理等进一步封装在一个c++类中来直接使用.
 *
 * 本测试的运行方法:test_plate_det [evdeploy_config] [test_image] [run_nums]
 * 输入参数为:1 配置文件 2 测试图片 3 连续推理次数
 * 例如:./bin/test_plate_det ./tests/configs/algo_license_plate_det_trt.json ./tests/data/plate_lic.jpg 5
 */

void test_model(std::string uuid, std::string image_name, int run_nums)
{
    ev::algo::LicensePlateDet plate_det("sophon", uuid); // 轀~I彋~K©atlas runtime
    for (int i = 0; i < run_nums; ++i)
    {
        cv::Mat inMat = cv::imread(image_name);
        std::vector<ev::vision::BoxInfo> bboxes;
        plate_det.Run(inMat, bboxes, 0.3);
        for (auto &it : bboxes)
        {
            EVLOG(INFO) << "detected:" << it.x1 << "," << it.x2 << "," << it.y1 << "," << it.y2 << "," << it.score;
        }
    }
}

int main(int argc, char **argv)
{

    std::vector<std::thread *> vec_threads{};
    // 根据配置文件初始化
    EVDeploy::GetModel().InitModel(argv[1]);

    // 解析配置文件
    std::ifstream inf(argv[1]);
    ev::Value value;
    ev::Reader j_reader;

    j_reader.parse(inf, value);
    value = value["serving_models"];

    std::string uuid;
    uuid = value[0]["uuid"].asString();
    EVLOG(INFO) << "uuid is:==========" << uuid;
    // 创建推理实例
    EVDeploy::GetModel().CreateModel(uuid);

    for (int i = 0; i < 4; i++) // 模拟多线程模型推理
    {
        vec_threads.push_back(new std::thread(test_model, uuid, std::string(argv[2]), atoi(argv[3])));
    }

    for (auto thread : vec_threads)
    {
        thread->join();
        delete thread;
    }

    // 释放资源
    EVDeploy::GetModel().DestroyModel(uuid);
    EVLOG(INFO) << "processing done!!";

    return 0;
}
